package cn.flying.cloud.oauth.server.configuration.aop;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import cn.flying.cloud.base.common.enums.RtCodeEnum;
import cn.flying.cloud.base.common.utils.Ft;
import cn.flying.cloud.base.common.vo.Rt;
import cn.flying.cloud.oauth.server.log.LoginLogHandler;

/**
 * oauth认证返回对象重构，修改为统一的格式
 *
 * @author: admin
 * @date: 2023年04月11日 20:54
 * @version: 1.0
 */
@Aspect
@Component
public class AuthTokenAspect {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private LoginLogHandler loginLogHandler;

    /**
     * 拦截令牌请求的端点
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
    public Object handleControllerMethod(ProceedingJoinPoint point) throws Throwable {
        // 获取请求参数
        Object[] args = point.getArgs();
        Map<String, String> parameters = (Map<String, String>) args[1];
        String username = parameters.get("username");
        String ip = null;
        // 通过RequestContextHolder获取当前请求
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            ip = Ft.Network.getIpAddress(request);
        }


        Rt<?> response;
        Object proceed = null;
        try {

            proceed = point.proceed();
            if (proceed == null) {
                return ResponseEntity.status(200).body(Rt.error(RtCodeEnum.R10020));
            }
            ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity<OAuth2AccessToken>) proceed;
            OAuth2AccessToken body = responseEntity.getBody();
            if (responseEntity.getStatusCode().is2xxSuccessful()) {
                response = Rt.success(body);
                loginLogHandler.loginSuccess(username, null, ip);
            } else {
                logger.error("OAuth认证异常，error:{}", responseEntity.getStatusCode());
                loginLogHandler.loginFailed(username, null, ip, responseEntity.getStatusCode().toString());
                response = Rt.error(RtCodeEnum.R10020);
            }
        } catch (Throwable throwable) {
            logger.error("OAuth认证异常", throwable);
            loginLogHandler.loginFailed(username, null, ip, throwable.getMessage());
            if (throwable instanceof OAuth2Exception) {
                response = Rt.result(RtCodeEnum.R10020, throwable.getMessage());
            } else {
                response = Rt.error(RtCodeEnum.R10020);
            }
        }

        return ResponseEntity.status(200).body(response);
    }
}